package com.yungam.imcs.controller.equip_stable.summary;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yungam.common.bean.equip.EquipStableScore;
import com.yungam.common.bean.equip.Equipment;
import com.yungam.common.bean.product.ProductionProduct;
import com.yungam.common.response.RetDTO;
import com.yungam.common.service.EquipStableScoreService;
import com.yungam.common.service.EquipmentService;
import com.yungam.common.utils.DateUtils;
import com.yungam.imcs.utils.CalculateScoreUtils;
import com.yungam.imcs.utils.ProductUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Api(tags = "设备稳定性页面接口")
@RestController
@RequestMapping("/equipStable")
public class EquipStableSummaryController {

    @Resource
    private ProductUtils productUtils;
    @Resource
    private DateUtils dateUtils;
    @Resource
    private CalculateScoreUtils calculateScoreUtils;
    @Resource
    private EquipStableScoreService equipStableScoreService;
    @Resource
    private EquipmentService equipmentService;

    /**
     * 表头的 key 为 `equ-${equId}` 的拼接
     * 便于前端固定顺序
     */
    @ApiOperation("查询表头")
    @GetMapping("/tableHead")
    public RetDTO<?> getTableHead() {
        List<Equipment> list = equipmentService.list(new QueryWrapper<Equipment>()
                .in("equ_id", calculateScoreUtils.getEquips())
                .select(Equipment.class, col -> !col.getProperty().equals("equImg")));
        List<Map<String, String>> ans = Lists.newArrayList();
        for (Equipment equipment : list) {
            Map<String, String> item = Maps.newHashMap();
            String key = "equ-" + equipment.getEquId();
            item.put("key", key);
            item.put("label", equipment.getEquName());
            ans.add(item);
        }

        return RetDTO.data(ans);
    }

    /**
    *  @description: 获取当日完成罐号稳定性数据
    */
    @ApiOperation("获取当日完成罐号稳定性数据")
    @GetMapping("/todayList")
    public RetDTO<?> getTodayEquipStablyData() {
        check(); // 检查有无新罐子未计算

        // 查询
        String[] range = dateUtils.getTodayRange();
        String start = range[0], end = range[1];
        List<EquipStableScore> list = equipStableScoreService.list(new QueryWrapper<EquipStableScore>()
                .between("create_time", start, end));
        // 按照罐号整合
        Map<String, List<EquipStableScore>> map = Maps.newHashMap();
        for (EquipStableScore es : list) {
            List<EquipStableScore> od = map.getOrDefault(es.getProductSn(), Lists.newArrayList());
            od.add(es);
            map.put(es.getProductSn(), od);
        }

        List<Map<String, Object>> ans = Lists.newArrayList();
        for (String s : map.keySet()) {
            Map<String, Object> item = Maps.newHashMap();
            item.put("productSn", s);
            List<EquipStableScore> scores = map.get(s);
            for (EquipStableScore es : scores) {
                String key = "equ-" + es.getEquId();
                item.put(key, es.getScore());
            }
            ans.add(item);
        }

        return RetDTO.data(ans);
    }

    /**
     * 检查有无新罐号完成, 有新完成的罐号则计算得分
     * 每隔1小时定时检查
     */
    @Scheduled(fixedRate = 1000 * 60 * 60)
    private void check() {
        String[] range = dateUtils.getTodayRange();
        String start = range[0], end = range[1];
        // 找出今日表中已插入的罐号
        List<EquipStableScore> exist = equipStableScoreService.list(new QueryWrapper<EquipStableScore>()
                .between("create_time", start, end));
        Set<String> existProductSns = new HashSet<>();
        for (EquipStableScore es : exist) {
            existProductSns.add(es.getProductSn());
        }

        // 查询今日已经完成的罐子
        List<ProductionProduct> finished = productUtils.getFinishedProduct();
        List<String> finishedNo = finished.stream()
                .map(ProductionProduct::getProductSn).collect(Collectors.toList());

        // 没有新完成的罐子  => （表中已有罐子数 === 已完成的罐子数）
        if (existProductSns.size() == finishedNo.size()) return;

        // 找出新完成的罐号
        List<String> fresh = Lists.newArrayList();
        for (String s : finishedNo) {
            if (!existProductSns.contains(s)) fresh.add(s);
        }

        insert(fresh); // 计算得分并保存到数据库
    }

    private void insert(List<String> productSnList) {
        List<EquipStableScore> res = calculateScoreUtils.calculate(productSnList);
        for (EquipStableScore re : res) {
            equipStableScoreService.save(re);
        }
    }

    /**
     *  @description: 获取历史完成罐号稳定性数据
     */
    @ApiOperation("获取历史完成罐号稳定性数据")
    @GetMapping("/historyList")
    public RetDTO<?> getHistoryEquipStablyData() {
        // 查询
        List<EquipStableScore> list = equipStableScoreService.list(new QueryWrapper<EquipStableScore>()
                .orderByAsc("create_time"));
        // 按照罐号整合
        Map<String, List<EquipStableScore>> map = Maps.newHashMap();
        Map<String, Date> dateMap = Maps.newHashMap();
        for (EquipStableScore es : list) {
            List<EquipStableScore> od = map.getOrDefault(es.getProductSn(), Lists.newArrayList());
            od.add(es);
            map.put(es.getProductSn(), od);
            dateMap.put(es.getProductSn(), es.getCreateTime());
        }

        List<Map<String, Object>> ans = Lists.newArrayList();
        for (String s : map.keySet()) {
            Map<String, Object> item = Maps.newHashMap();
            item.put("productSn", s);
            List<EquipStableScore> scores = map.get(s);
            for (EquipStableScore es : scores) {
                String key = "equ-" + es.getEquId();
                item.put(key, es.getScore());
            }
            ans.add(item);
        }
        // 按照罐号结束时间倒序
        ans.sort((a, b) -> {
            long x = dateMap.get(a.get("productSn")).getTime(),
                    y = dateMap.get(a.get("productSn")).getTime();
            return (int) (y - x);
        });
        return RetDTO.data(ans);
    }

}
